using System;

namespace Tycho.Parser.Peg {
    public class DelimitedRule : Rule {
        private readonly IRule Delimiter;
        private readonly IRule Item;

        public DelimitedRule (IRule item, IRule delimiterRule) {
            Item = item;
            Delimiter = delimiterRule;
        }

        public override Yield Parse (char[] source, int index, ParseContext context, string sourceString, ParseEnvironment environment, Func<RuleParseResult, Yield> continuation) {
            return Item.Parse (source, index, context, sourceString, environment, itemResult => {
                if (itemResult != null) {
                    return ParseNextItem (source, sourceString, environment, itemResult, continuation);
                } else {
                    return () => continuation (new RuleParseResult (index, context));
                }
            });
        }

        private Yield ParseNextItem (char[] source, string sourceString, ParseEnvironment environment, RuleParseResult itemResult, Func<RuleParseResult, Yield> continuation) {
            return Delimiter.Parse (source, itemResult.Index, itemResult.Context, sourceString, environment, delimiterResult => {
                if (delimiterResult == null) {
                    return () => continuation (itemResult);
                }

                delimiterResult.MergeCapturesFrom (itemResult);

                return Item.Parse (source, delimiterResult.Index, delimiterResult.Context, sourceString, environment, nextItemResult => {
                    if (nextItemResult == null) {
                        return () => continuation (delimiterResult);
                    } else {
                        nextItemResult.MergeCapturesFrom (delimiterResult);
                        itemResult = nextItemResult;
                    }

                    return () => ParseNextItem (source, sourceString, environment, itemResult, continuation);
                });
            });
        }
    }
}